#include "pmm.h"
#include "memory.h"
#include "spinlock.h"
#include "string.h"
#include "printf.h"
#include "panic.h"

struct run {
    struct run *next;
};

struct {
    spinlock lock;
    struct run *freelist;
} kmem;

// 静态函数前置声明
static void freerange(void *pa_start, void *pa_end);

void pmm_init(void) {
    initlock(&kmem.lock, "kmem");
    freerange(end, (void*)PHYSTOP);
}

static void freerange(void *pa_start, void *pa_end) {
    char *p = (char*)PGROUNDUP((uint64)pa_start);
    for (; p + PGSIZE <= (char*)pa_end; p += PGSIZE)
        free_page(p);
}

void free_page(void *pa) {
    if ((uint64)pa % PGSIZE != 0 || (char*)pa < end || (uint64)pa >= PHYSTOP)
        panic("free_page: invalid pa");

    memset(pa, 1, PGSIZE); // 填充垃圾值

    struct run *r = (struct run*)pa;
    acquire(&kmem.lock);
    r->next = kmem.freelist;
    kmem.freelist = r;
    release(&kmem.lock);
}

void *alloc_page(void) {
    acquire(&kmem.lock);
    struct run *r = kmem.freelist;
    if (r)
        kmem.freelist = r->next;
    release(&kmem.lock);

    if (r)
        memset((char*)r, 5, PGSIZE); // 填充调试值
    return (void*)r;
}
